<script setup lang="ts">
import {
  DragOutlined,
  SettingOutlined,
  VerticalLeftOutlined,
  VerticalRightOutlined,
} from '@vicons/antd';
import Draggable from 'vuedraggable';
import { cloneDeep } from 'lodash-es';

import { useAppearanceSettingStore } from '@/store/modules/appearance-setting';
import type { RetInstance } from '@/components/table/src/context/use-table-context';
import { useTableContext } from '@/components/table/src/context/use-table-context';
import type { BasicTableColumn } from '@/components/table';

defineOptions({
  name: 'ColumnSetting',
});

interface Options {
  title: string;
  key: string;
  fixed?: undefined | 'left' | 'right';
}

const table: RetInstance = useTableContext();

watchEffect(() => {
  const columns = table.getColumns();
  if (columns.length) {
    nextTick().then(() => {
      init();
    });
  }
});

const columnsList = ref<Options[]>([]);
const cacheColumnsList = ref<Options[]>([]);
const checkList = ref<string[]>([]);
const defaultCheckList = ref<string[]>([]);

/**
 * 获取
 */
function getColumns() {
  const newRet: BasicTableColumn[] = [];
  table.getColumns().forEach(item => {
    newRet.push({ ...item });
  });
  return newRet;
}

/**
 * 设置
 * @param columns
 */
function setColumns(columns: string[]) {
  table.setColumns(columns);
}

/**
 * 初始化
 */
function init() {
  const columns = getColumns().filter(item => item.display ?? true);
  checkList.value = columns.filter(item => item.key !== 'action').map(item => item.key);
  defaultCheckList.value = checkList.value;
  const newColumns = columns.filter(item => item.key !== 'action')
    .map(item => {
      return {
        title: item.title as string,
        key: item.key,
        fixed: undefined,
      };
    });
  if (!columnsList.value.length) {
    columnsList.value = cloneDeep(newColumns);
    cacheColumnsList.value = cloneDeep(newColumns);
  }
}
/**
 * 切换
 */
function onChange(checkList: string[]) {
  setColumns(checkList);
}

/**
 * 全选
 */
const checkAll = ref(true);
function onCheckAll(check: boolean) {
  checkAll.value = check;
  const cacheKeys = table.getCacheColumns(true);
  if (check) {
    checkList.value = cacheKeys as string[];
    setColumns(cacheKeys as string[]);
  } else {
    checkList.value = [];
    setColumns([]);
  }
}

/**
 * 勾选列
 */
const selection = ref(true);
function onSelection(value: boolean) {
  selection.value = value;
  table.setSelection(value);
}

/**
 * 重置
 */
function resetColumns() {
  checkList.value = defaultCheckList.value;
  columnsList.value = cacheColumnsList.value;
}

/**
 * 拖拽排序
 */
function onMove(e: any) {
  return e.draggedContext.element.draggable !== false;
}
function draggableEnd() {
  const newColumns = unref(columnsList);
  columnsList.value = newColumns;
  const keys = newColumns.map(item => item.key);
  setColumns(keys);
}

/**
 * 固定
 */
function fixedColumn(item: Options, fixed: undefined | 'left' | 'right') {
  if (!checkList.value.includes(item.key)) {
    return;
  }
  const isFixed = item.fixed === fixed ? undefined : fixed;
  const index = columnsList.value.findIndex(res => res.key === item.key);
  if (index !== -1) {
    columnsList.value[index].fixed = isFixed;
  }

  table.setCacheColumnsField(item.key, { fixed: isFixed });

  const keys = columnsList.value.map(item => item.key);
  setColumns(keys);
}

const appTheme = computed(() => useAppearanceSettingStore().appTheme);
const darkTheme = computed(() => useAppearanceSettingStore().darkTheme);
</script>

<template>
  <NTooltip trigger="hover">
    <template #trigger>
      <div class="cursor-pointer table-toolbar-right-icon">
        <NPopover trigger="click" class="toolbar-popover" placement="bottom-end">
          <template #trigger>
            <NIcon size="18">
              <SettingOutlined />
            </NIcon>
          </template>

          <template #header>
            <div class="table-toolbar-inner-popover-title">
              <NSpace justify="space-between">
                <NCheckbox v-model:checked="checkAll" @update:checked="onCheckAll">
                  全选
                </NCheckbox>
                <NCheckbox v-model:checked="selection" @update:checked="onSelection">
                  勾选列
                </NCheckbox>
                <NButton text type="info" size="small" class="mt-1" @click="resetColumns">
                  重置
                </NButton>
              </NSpace>
            </div>
          </template>
          <div class="table-toolbar-inner">
            <NCheckboxGroup v-model:value="checkList" @update:value="onChange">
              <Draggable
                v-model="columnsList"
                animation="300"
                item-key="key"
                filter=".no-draggable"
                :move="onMove"
                @end="draggableEnd"
              >
                <template #item="{ element }">
                  <div
                    class="table-toolbar-inner-checkbox"
                    :class="{
                      'table-toolbar-inner-checkbox-dark': darkTheme === true,
                      'no-draggable': element.draggable === false,
                    }"
                  >
                    <span
                      class="drag-icon"
                      :class="{ 'drag-icon-hidden': element.draggable === false }"
                    >
                      <NIcon size="18">
                        <DragOutlined />
                      </NIcon>
                    </span>
                    <NCheckbox :value="element.key" :label="element.title" />
                    <div class="fixed-item">
                      <NTooltip trigger="hover" placement="bottom">
                        <template #trigger>
                          <NIcon
                            size="18"
                            :color="element.fixed === 'left' ? appTheme : undefined"
                            class="cursor-pointer"
                            @click="fixedColumn(element, 'left')"
                          >
                            <VerticalRightOutlined />
                          </NIcon>
                        </template>
                        <span>固定到左侧</span>
                      </NTooltip>
                      <NDivider vertical />
                      <NTooltip trigger="hover" placement="bottom">
                        <template #trigger>
                          <NIcon
                            size="18"
                            :color="element.fixed === 'right' ? appTheme : undefined"
                            class="cursor-pointer"
                            @click="fixedColumn(element, 'right')"
                          >
                            <VerticalLeftOutlined />
                          </NIcon>
                        </template>
                        <span>固定到右侧</span>
                      </NTooltip>
                    </div>
                  </div>
                </template>
              </Draggable>
            </NCheckboxGroup>
          </div>
        </NPopover>
      </div>
    </template>
    列设置
  </NTooltip>
</template>

<style lang="less">
.table-toolbar {
  &-inner-popover-title {
    padding: 3px 0;
  }

  &-right {
    &-icon {
      margin-left: 12px;
      font-size: 16px;
      color: var(--text-color);
      cursor: pointer;

      :hover {
        color: v-bind(appTheme);
      }
    }
  }
}

.table-toolbar-inner {
  &-checkbox {
    display: flex;
    align-items: center;
    padding: 10px 14px;

    &:hover {
      background: #e6f7ff;
    }

    .drag-icon {
      display: inline-flex;
      margin-right: 8px;
      cursor: move;
      &-hidden {
        visibility: hidden;
        cursor: default;
      }
    }

    .fixed-item {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      margin-left: auto;
    }

    .ant-checkbox-wrapper {
      flex: 1;

      &:hover {
        color: v-bind(appTheme) !important;
      }
    }
  }

  &-checkbox-dark {
    &:hover {
      background: hsla(0, 0%, 100%, 0.08);
    }
  }
}

.toolbar-popover {
  .n-popover__content {
    padding: 0;
  }
}
</style>
